package com.gitee.tje.waving.context;

import com.gitee.tje.waving.beans.BeanDefinition;
import com.gitee.tje.waving.beans.BeanFactoryProcessor;
import com.gitee.tje.waving.factory.BaseBeanFactory;
import com.gitee.tje.waving.factory.BeanFactory;

import java.util.ArrayList;
import java.util.Collection;
import java.util.List;

/**
 * bean工厂
 *
 * @author taojiaen
 * @date 2018-01-08 08:48
 */
public class BeanContext implements BeanFactory{
    private final BaseBeanFactory beanFactory;


    private List<BeanFactoryProcessor> beanFactoryProcessors = new ArrayList<>();


    public BeanContext(Collection<BeanDefinition> beanDefinitionCollections) {
        this(beanDefinitionCollections, null);
    }

    public BeanContext(Collection<BeanDefinition> beanDefinitionCollections,
                       BeanContext parent) {
        this(beanDefinitionCollections, parent, Thread.currentThread().getContextClassLoader());
    }

    public BeanFactory getBeanFactory() {
        return beanFactory;
    }

    public BeanContext(Collection<BeanDefinition> beanDefinitionCollections,
                       BeanContext parent, ClassLoader classLoader)  {

        if (parent != null) {
            this.beanFactory = new BaseBeanFactory(parent.getBeanFactory(), classLoader);
        } else {
            this.beanFactory = new BaseBeanFactory(classLoader);
        }
        for (BeanDefinition beanDefinitionCollection : beanDefinitionCollections) {
           register(beanDefinitionCollection);
        }

        refresh();
    }





    @Override
    public Object getBean(String beanName) {

        return beanFactory.getBean(beanName);
    }

    @Override
    public Collection<String> getBeanName(Class<?> clazz) {
        return beanFactory.getBeanName(clazz);
    }

    @Override
    public void createAllSingleObj(){
        beanFactory.createAllSingleObj();

    }

    @Override
    public void register(BeanDefinition beanDefinition) {
        beanFactory.register(beanDefinition);
    }

    public void refresh() {
        beanFactory.destroy();
        invokeBeanFactoryProcessor();
        beanFactory.createAllSingleObj();
    }

    private void invokeBeanFactoryProcessor() {
        for (String beanName : getBeanName(BeanFactoryProcessor.class)) {
            beanFactoryProcessors.add((BeanFactoryProcessor) getBean(beanName));
        }
        for (BeanFactoryProcessor beanFactoryProcessor : beanFactoryProcessors) {
           beanFactoryProcessor.processBeanFactory(beanFactory);
        }
    }

    @Override
    public void destroy() {
        beanFactory.destroy();
    }

}
